package com.atguigu.tingshu.payment.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.common.Assert;

import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.order.client.OrderInfoFeignClient;
import com.atguigu.tingshu.payment.config.WxPayV3Config;
import com.atguigu.tingshu.payment.service.PaymentInfoService;
import com.atguigu.tingshu.payment.service.WxPayService;
import com.atguigu.tingshu.payment.util.PayUtil;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.model.QueryOrderByOutTradeNoRequest;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author sun
 */
@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

    @Resource
    private PaymentInfoService paymentInfoService;
    @Resource
    private OrderInfoFeignClient orderInfoFeignClient;
    @Resource
    private RSAAutoCertificateConfig rsaAutoCertificateConfig;
    @Resource
    private WxPayV3Config wxPayV3Config;
    @Resource
    private UserInfoFeignClient userInfoFeignClient;
    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    /**
     * 获取支付url
     *
     * @param type    支付类型 1301-订单 1302-充值
     * @param orderNo 订单号
     * @return 返回的参数供页面使用
     */

    @Override
    public Map<String, Object> creatJsapi(String type, String orderNo) {

//        try {
//            // 充值不需要判断订单是否取消
//            if (type.equals(SystemConstant.PAYMENT_TYPE_ORDER)) {
//                // 订单取消不能生成二维码
//                Result<OrderInfo> orderInfoResult = orderInfoFeignClient.getOrderInfo(orderNo);
//                Assert.notNull(orderInfoResult, ResultCodeEnum.ORDER_INFO_REMOTE_CALL_ERROR);
//                OrderInfo orderInfo = orderInfoResult.getData();
//                Assert.isTrue(orderInfo.getOrderStatus().equals(SystemConstant.ORDER_STATUS_UNPAID), ResultCodeEnum.ORDER_PAY_ERROR);
//            }
//
//            // 保存支付记录
//            PaymentInfo paymentInfo = paymentInfoService.savePaymentInfo(type, orderNo);
//            // 构建service
//            JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();
//            PrepayRequest prepayRequest = new PrepayRequest();
//            Amount amount = new Amount();
//            amount.setTotal(1);
//            // 默认为人民币支付
//            amount.setCurrency("CNY");
//            prepayRequest.setAmount(amount);
//            prepayRequest.setAppid(wxPayV3Config.getAppid());
//            prepayRequest.setMchid(wxPayV3Config.getMerchantId());
//            prepayRequest.setNotifyUrl(wxPayV3Config.getNotifyUrl());
//            prepayRequest.setDescription(paymentInfo.getContent());
//            prepayRequest.setOutTradeNo(orderNo);
//            // 获取用户信息
//            Result<UserInfoVo> userInfoResult = userInfoFeignClient.getUserInfoVo();
//            Assert.notNull(userInfoResult, ResultCodeEnum.USERINFO_REMOTE_CALL_ERROR);
//            UserInfoVo userInfoVo = userInfoResult.getData();
//            Payer payer = new Payer();
//            payer.setOpenid(userInfoVo.getWxOpenId());
//            prepayRequest.setPayer(payer);
//            // 调用微信的下单方法
//            PrepayWithRequestPaymentResponse prepayWithRequestPaymentResponse = service.prepayWithRequestPayment(prepayRequest);
//            log.info("微信支付下单返回结果{}", JSONObject.toJSONString(prepayWithRequestPaymentResponse));
//            Map<String, Object> map = new HashMap<>();
//            map.put("timeStamp", prepayWithRequestPaymentResponse.getTimeStamp());
//            map.put("nonceStr", prepayWithRequestPaymentResponse.getNonceStr());
//            map.put("package", prepayWithRequestPaymentResponse.getPackageVal());
//            map.put("signType", prepayWithRequestPaymentResponse.getSignType());
//            map.put("paySign", prepayWithRequestPaymentResponse.getPaySign());
//            return map;
//        } catch (GuiguException e) {
//            throw e;
//        } catch (Exception e) {
//            throw new GuiguException(ResultCodeEnum.WEIXIN_PLACE_ORDER_ERROR);
//        }
        return null;
    }


    /**
     * 获取支付二维码
     *
     * @param type    支付类型：1301-订单 1302-充值
     * @param orderNo 订单号
     * @return 二维码地址
     */
    @Override
    public String getNativeUrl(String type, String orderNo) {
        Result<OrderInfo> orderInfoResult = orderInfoFeignClient.getOrderInfo(orderNo);
        Assert.notNull(orderInfoResult, ResultCodeEnum.ORDER_INFO_REMOTE_CALL_ERROR);
        OrderInfo orderInfo = orderInfoResult.getData();

        NativePayService service = new NativePayService.Builder()
                .config(rsaAutoCertificateConfig).build();
        PrepayRequest prepayRequest = new PrepayRequest();
        Amount amount = new Amount();
        // 订单金额
        amount.setTotal(1);
        // 默认为人民币支付
        amount.setCurrency("CNY");
        prepayRequest.setAmount(amount);
        prepayRequest.setAppid(wxPayV3Config.getAppid());
        prepayRequest.setMchid(wxPayV3Config.getMerchantId());
        prepayRequest.setNotifyUrl(wxPayV3Config.getNotifyUrl());
        prepayRequest.setDescription(orderInfo.getOrderTitle());
        prepayRequest.setOutTradeNo(orderNo);
        PrepayResponse prepay = service.prepay(prepayRequest);
        if (prepay.getCodeUrl() != null) {
            return prepay.getCodeUrl();
        }
        return "";
    }

    /**
     * 查询支付状态
     *
     * @param orderNo 订单号
     * @return 返回的参数
     */
    @Override
    public Transaction queryPayStatus(String orderNo) {

        // 构建service
        NativePayService service = new NativePayService.Builder().config(rsaAutoCertificateConfig).build();
        QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
        queryRequest.setMchid(wxPayV3Config.getMerchantId());
        queryRequest.setOutTradeNo(orderNo);
        Transaction transaction = service.queryOrderByOutTradeNo(queryRequest);

        if (transaction.getTradeState().equals(Transaction.TradeStateEnum.SUCCESS)) {
            // 更新支付记录
            CompletableFuture.runAsync(() -> paymentInfoService.updatePaymentStatus(transaction),threadPoolExecutor);
        }
        return transaction;
    }


    /**
     * 微信支付回调
     *
     * @param request 请求
     * @return 返回的参数
     */
    @Override
    public Boolean wxPayNotify(HttpServletRequest request) {

        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String signature = request.getHeader("Wechatpay-Signature");
        // 调用工具类来获取请求体数据
        try {
            String requestBody = PayUtil.readData(request);

            RequestParam requestParam = new RequestParam.Builder()
                    .body(requestBody)
                    .nonce(nonce)
                    .serialNumber(wechatPaySerial)
                    .timestamp(timestamp)
                    .signature(signature)
                    .build();

            NotificationParser notificationParser = new NotificationParser(rsaAutoCertificateConfig);

            Transaction transaction = notificationParser.parse(requestParam, Transaction.class);
            log.info("微信支付回调参数{}", JSONObject.toJSONString(transaction));
            if (transaction.getTradeState().equals(Transaction.TradeStateEnum.SUCCESS)) {
                CompletableFuture.runAsync(() -> paymentInfoService.updatePaymentStatus(transaction),threadPoolExecutor);
                return true;
            }
            return false;
        } catch (ValidationException e) {
            log.error("sign verification failed", e);
            return false;
        } catch (IOException e) {
            log.error("read data failed", e);
            return false;
        }
    }
}
